// ----------------------
// projects/life/main.c++
// Copyright (C) 2009
// Glenn P. Downing
// ----------------------

/*
To run the tests:
    g++ -ansi -pedantic -lcppunit -ldl -Wall -DTEST main.c++ -o main.app
    main.app

To run the program:
    g++ -ansi -pedantic -Wall main.c++ -o main.app
    main.app
*/

// --------
// includes
// --------

#include <cassert>   // assert
#include <iostream>  // cout, endl
#include <stdexcept> // invalid_argument, out_of_range
#include <fstream>
#include "Life.h"

#ifdef TEST
    #include "cppunit/TestSuite.h"      // TestSuite
    #include "cppunit/TextTestRunner.h" // TestRunner

    #include "TestLife.h"
#endif // TEST

// ----
// main
// ----

int main () {
    using namespace std;

    #ifdef TEST
        // ----------
        // unit tests
        // ----------

        using namespace CppUnit;

        TextTestRunner tr;
        tr.addTest(TestLife::suite());
        tr.run();
    #else
        // -------
        // program
        // -------
    
        // -----------------------
        // life conway cell 109x69
        // -----------------------
    
        try {
            cout << "*** Life<ConwayCell> 109x69 ***" << endl;
            int x;
	    int y;
	    std::ifstream in("LifeConwayCell.in");
	    in>>x;
	    in>>y;
	    Life<ConwayCell> l(x, y);
	    l.readConwayorFredkin(in);
	    cout<<l;
	    for(int i=0; i<283; i++)
		l.turn();
	    cout<<l;
	    for(int i=0; i<40; i++)l.turn();
	    cout<<l;
	    for(int i=0; i<2177; i++)l.turn();
	    cout<<l;
	    in.close();
            }
        catch (const invalid_argument&) {
            assert(false);}
        catch (const out_of_range&) {
            assert(false);}

        // -----------------------
        // life fredkin cell 20x20
        // -----------------------
    
        try {
            cout << "*** Life<FredkinCell> 20x20 ***" << endl;
	    int x, y;
	    std::ifstream in("LifeFredkinCell.in");
	    in>>x;
	    in>>y;
	    Life<FredkinCell> l(x, y);
	    l.readConwayorFredkin(in);
	    cout<<l;
	    l.turn();
	    cout<<l;
	    l.turn();
	    cout<<l;
	    in.close();
            }
        catch (const invalid_argument&) {
            assert(false);}
        catch (const out_of_range&) {
            assert(false);}

        // ---------------
        // life cell 20x20
        // ---------------
    
        try {
            cout << "*** Life<Cell> 20x20 ***" << endl;
            int x, y;
	    std::ifstream in("LifeCell.in");
	    in>>x;
	    in>>y;
	    Life<Cell> l(x, y);
	    l.readCellGrid(in);
	    cout<<l;
	    for(int i=0; i<5; i++){
		l.turn(); cout<<l;}
	    in.close();
            }
        catch (const invalid_argument&) {
            assert(false);}
        catch (const out_of_range&) {
            assert(false);}
    #endif // NDEBUG

    return 0;}
